home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Utilities / BasiliskII / src / BeOS / SheepNet / sheep_net.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-31  |  7.7 KB  |  295 lines

  1. /*
  2.  *  sheep_net.cpp - Net server add-on for SheepShaver and Basilisk II
  3.  *
  4.  *  SheepShaver (C) 1997-2001 Mar"c" Hellwig and Christian Bauer
  5.  *  Basilisk II (C) 1997-2001 Christian Bauer
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with this program; if not, write to the Free Software
  19.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20.  */
  21.  
  22. #include <KernelKit.h>
  23. #include <SupportKit.h>
  24. #include <add-ons/net_server/NetDevice.h>
  25. #include <add-ons/net_server/NetProtocol.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <stdarg.h>
  29. #include <string.h>
  30. #include <time.h>
  31.  
  32. #include "sheep_net.h"
  33.  
  34. #define DEBUG 0
  35.  
  36. #if DEBUG==1
  37. #define bug pprintf
  38. #elif DEBUG==2
  39. #define bug kprintf
  40. #endif
  41.  
  42. #if DEBUG
  43. #define D(x) (x)
  44. #else
  45. #define D(x) ;
  46. #endif
  47.  
  48. static int pprintf(const char* format, ...)
  49. {
  50.     port_id PortNum;
  51.     int len,Ret;
  52.     char Buffer[1024];
  53.     va_list ap;
  54.     
  55.     if ((PortNum = find_port("PortLogger")) == B_NAME_NOT_FOUND)
  56.         return(PortNum);
  57.     for (len=0; len<1024; len++)
  58.         Buffer[len]='\0'; 
  59.     va_start(ap, format);
  60.     vsprintf(Buffer, format, ap);
  61.     Ret = write_port(PortNum, 0, Buffer, strlen(Buffer));
  62.     return(Ret);
  63. }
  64.  
  65.  
  66. // Constants
  67. #define NETDUMP_PRIO 1        // Default is 0
  68.  
  69. const uint32 buffer_size = (sizeof(net_buffer) / B_PAGE_SIZE + 1) * B_PAGE_SIZE;
  70.  
  71.  
  72. // SheepNet add-on object
  73. class SheepNetAddOn : public BNetProtocol, BPacketHandler {
  74. public:
  75.     void AddDevice(BNetDevice *dev, const char *name);
  76.     bool PacketReceived(BNetPacket *buf, BNetDevice *dev);
  77. };
  78.  
  79.  
  80. // Global variables
  81. static bool shutdown_now = false; 
  82. static bool    active = false;
  83.  
  84. static thread_id write_thread;            // Packet writer
  85. static sem_id write_sem;                // Semaphore to trigger packet writing
  86. static BNetDevice *EtherCard = NULL;    // The Ethernet card we are attached to
  87. static area_id buffer_area;                // Packet buffer area
  88. static net_buffer *net_buffer_ptr;        // Pointer to packet buffer
  89.  
  90. static uint32 rd_pos;                    // Current read position in packet buffer
  91. static uint32 wr_pos;                    // Current write position in packet buffer
  92.  
  93.  
  94. /*
  95.  *  Clear packet buffer
  96.  */
  97.  
  98. static void clear(void)
  99. {
  100.     int i;
  101.     for (i=0;i<READ_PACKET_COUNT;i++) {
  102.         net_buffer_ptr->read[i].cmd = 0;
  103.         net_buffer_ptr->read[i].length = 0;
  104.         net_buffer_ptr->read[i].card = 0;
  105.         net_buffer_ptr->read[i].reserved = 0;
  106.     }
  107.     for (i=0;i<WRITE_PACKET_COUNT;i++) {
  108.         net_buffer_ptr->write[i].cmd = 0;
  109.         net_buffer_ptr->write[i].length = 0;
  110.         net_buffer_ptr->write[i].card = 0;
  111.         net_buffer_ptr->write[i].reserved = 0;
  112.     }
  113.     rd_pos = wr_pos = 0;
  114. }
  115.  
  116.  
  117. /*
  118.  *  Packet writer thread
  119.  */
  120.  
  121. static status_t write_packet_func(void *arg)
  122. {
  123.     while (!shutdown_now) {
  124.  
  125.         // Read and execute command
  126.         net_packet *p = &net_buffer_ptr->write[wr_pos];
  127.         while (p->cmd & IN_USE) {
  128.             D(bug("wp: %d\n", wr_pos));
  129.             switch (p->cmd >> 8) {
  130.  
  131.                 case ACTIVATE_SHEEP_NET:
  132.                     D(bug("activate sheep-net\n"));
  133.                     active = false;
  134.                     clear();
  135.                     active = true;
  136.                     goto next;
  137.  
  138.                 case DEACTIVATE_SHEEP_NET:
  139.                     D(bug("deactivate sheep-net\n"));
  140.                     active = false;
  141.                     clear();
  142.                     goto next;
  143.  
  144.                 case SHUTDOWN_SHEEP_NET:
  145.                     D(bug("shutdown sheep-net\n"));
  146.                     active = false;
  147.                     clear();
  148.                     shutdown_now = true;
  149.                     goto next;
  150.  
  151.                 case ADD_MULTICAST: {
  152.                     const char *data = (const char *)p->data;
  153.                     D(bug("add multicast %02x %02x %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3], data[4], data[5]));
  154.                     if (active) {
  155.                         status_t result;
  156.                         if ((result = EtherCard->AddMulticastAddress(data)) != B_OK) {
  157.                             // !! handle error !! error while creating multicast address
  158.                             D(bug("error while creating multicast address %d\n", result));
  159.                         }
  160.                     }
  161.                     break;
  162.                 }
  163.  
  164.                 case REMOVE_MULTICAST: {
  165.                     const char *data = (const char *)p->data;
  166.                     D(bug("remove multicast %02x %02x %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3], data[4], data[5]));
  167.                     if (active) {
  168.                         status_t result;
  169.                         if ((result = EtherCard->RemoveMulticastAddress(data)) != B_OK) {
  170.                             // !! handle error !! error while removing multicast address
  171.                             D(bug("error while removing multicast address %d\n", result));
  172.                         }
  173.                     }
  174.                     break;
  175.                 }
  176.  
  177.                 case SHEEP_PACKET: {
  178.                     uint32 length = p->length;
  179.                     // D(bug("sheep packet %d\n", length));
  180.                     if (active) {
  181.                         BStandardPacket *packet = new BStandardPacket(length);
  182.                         packet->Write(0, (const char *)p->data, length);
  183.                         EtherCard->SendPacket(packet);
  184.                     }
  185.                     break;
  186.                 }
  187.  
  188.                 default:
  189.                     D(bug("error: unknown port packet type\n"));
  190.                     break;
  191.             }
  192.             p->cmd = 0;    // Free packet                    
  193.             wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT;
  194.             p = &net_buffer_ptr->write[wr_pos];
  195.         }
  196.  
  197.         // Wait for next packet
  198. next:    acquire_sem_etc(write_sem, 1, B_TIMEOUT, 25000);
  199.     }
  200.     return 0;
  201. }
  202.  
  203.  
  204. /*
  205.  *  Init the net add-on
  206.  */
  207.  
  208. static void init_addon()
  209. {
  210.     int i;
  211.     D(bug("init sheep-net\n"));
  212.  
  213.     // Create packet buffer
  214.     if ((buffer_area = create_area("packet buffer", (void **)&net_buffer_ptr, B_ANY_ADDRESS, buffer_size, B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA)) < B_NO_ERROR) {
  215.         D(bug("FATAL ERROR: can't create shared area\n"));
  216.         return;
  217.     }    
  218.  
  219.     // Init packet buffer
  220.     clear();
  221.     EtherCard->Address((char *)net_buffer_ptr->ether_addr);
  222.     net_buffer_ptr->read_sem = -1;
  223.     net_buffer_ptr->read_ofs = (uint32)(net_buffer_ptr->read) - (uint32)net_buffer_ptr;
  224.     net_buffer_ptr->read_packet_size = sizeof(net_packet);
  225.     net_buffer_ptr->read_packet_count = READ_PACKET_COUNT;
  226.     if ((write_sem = create_sem(0, "ether write")) < B_NO_ERROR) {
  227.         D(bug("FATAL ERROR: can't create semaphore\n"));
  228.         return;
  229.     }
  230.     net_buffer_ptr->write_sem = write_sem;
  231.     net_buffer_ptr->write_ofs = (uint32)(net_buffer_ptr->write) - (uint32)net_buffer_ptr;
  232.     net_buffer_ptr->write_packet_size = sizeof(net_packet);
  233.     net_buffer_ptr->write_packet_count = WRITE_PACKET_COUNT;
  234.  
  235.     // Start packet writer thread
  236.     write_thread = spawn_thread(write_packet_func, "sheep_net ether write", B_URGENT_DISPLAY_PRIORITY, NULL);
  237.     resume_thread(write_thread);
  238. }
  239.  
  240.  
  241. /*
  242.  *  Add-on attached to Ethernet card
  243.  */
  244.  
  245. void SheepNetAddOn::AddDevice(BNetDevice *dev, const char *name)
  246. {
  247.     if (dev->Type() != B_ETHER_NET_DEVICE)
  248.         return;
  249.     if (EtherCard != NULL) {
  250.         // !! handle error !! support for multiple ethernet cards ...
  251.         D(bug("error: SheepShaver doesn't support multiple Ethernetcards !\n"));
  252.         return;
  253.     }
  254.     EtherCard = dev;
  255.     init_addon();
  256.     register_packet_handler(this, dev, NETDUMP_PRIO);
  257. }
  258.  
  259.  
  260. /*
  261.  *  Ethernet packet received
  262.  */
  263.  
  264. bool SheepNetAddOn::PacketReceived(BNetPacket *pkt, BNetDevice *dev)
  265. {
  266.     if (shutdown_now) {
  267.         unregister_packet_handler(this, dev);
  268.         return false;
  269.     }
  270. //    D(bug("read_packet_func %d\n", pkt->Size()));
  271.     if (active) {
  272.         D(bug("rp: %d\n", rd_pos));
  273.         net_packet *p = &net_buffer_ptr->read[rd_pos];
  274.         if (p->cmd & IN_USE) {
  275.             D(bug("error: full read buffer ... lost packet\n"));
  276.         } else {
  277.             memcpy(p->data, pkt->Data(), pkt->Size());
  278.             p->length = pkt->Size();
  279.             p->cmd = IN_USE | (SHEEP_PACKET << 8);
  280.             rd_pos = (rd_pos + 1) % READ_PACKET_COUNT;
  281.             release_sem(net_buffer_ptr->read_sem);
  282.         }
  283.     }
  284.     //D(bug("%02x %02x %02x %02x %02x %02x", (uchar) (pkt->Data())[0],(uchar) (pkt->Data())[1],(uchar) (pkt->Data())[2],(uchar) (pkt->Data())[3],(uchar) (pkt->Data())[4],(uchar) (pkt->Data())[5]));
  285.     return false;
  286. }
  287.  
  288. #pragma export on
  289. extern "C" BNetProtocol *open_protocol(const char *device)
  290. {
  291.     SheepNetAddOn *dev = new SheepNetAddOn;
  292.     return dev;
  293. }
  294. #pragma export off
  295.